﻿using System;
using System.Net;

namespace QuailSeleniumManager
{
    /// <summary>
    /// Delegate for receiving a web request
    /// </summary>
    /// <param name="context">the context of the request</param>
    public delegate void DelReceiveWebRequest(HttpListenerContext context);

    /// <summary>
    /// Wrapper class for the HTTPListener to allow easier access to the
    /// server, for start and stop management and event routing of the actual
    /// inbound requests.
    /// </summary>
    public class HttpServer
    {
        private HttpListener _listener;
 
        /// <summary>
        /// The ReceiveWebRequest event
        /// </summary>
        public event DelReceiveWebRequest ReceiveWebRequest;
 
        /// <summary>
        /// Starts the Web Service
        /// </summary>
        /// <param name="urlBase">
        /// A Uri that acts as the base that the server is listening on.
        /// Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/
        /// Note: the trailing backslash is required! For more info see the
        /// HttpListener.Prefixes property on MSDN.
        /// </param>
        public void Start(string urlBase)
        {
            // *** Already running - just leave it in place
            if (_listener != null)
                return;
 
            var listener = new HttpListener();
 
            listener.Prefixes.Add(urlBase);

            // if you get Access denied exception here on Vista: 
            // run this on administrator command line (replace domain\user with your domain and user account):
            //     netsh http add urlacl url=http://*:2525/ user=domain\user
            listener.Start();

            _listener = listener;
            _listener.BeginGetContext(WebRequestCallback, _listener);
        }
 
        /// <summary>
        /// Shut down the Web Service
        /// </summary>
        public void Stop()
        {
            if (_listener != null)
            {
                _listener.Close();
                _listener = null;
            }
        }
 
        /// <summary>
        /// A webrequest is complete
        /// </summary>
        /// <param name="result">the result of the request</param>
        protected void WebRequestCallback(IAsyncResult result)
        {
            if (_listener == null)
                return;

            try
            {
                // Get out the context object
                HttpListenerContext context = _listener.EndGetContext(result);

                // *** Immediately set up the next context
                _listener.BeginGetContext(WebRequestCallback, _listener);

                if (ReceiveWebRequest != null)
                    ReceiveWebRequest(context);

                ProcessRequest(context);
            }
            catch
            {
            }
        }
 
        /// <summary>
        /// Overridable method that can be used to implement a custom hnandler
        /// </summary>
        /// <param name="context">the context of the request</param>
        protected virtual void ProcessRequest(HttpListenerContext context)
        {
        }
    }
}
